﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;

namespace Moon.Sql
{
    internal class MemberExpressionProvider
    {
        private ExpressionProvide _expression = null;

        public MemberExpressionProvider(ExpressionProvide expression)
        {
            _expression = expression;
        }

        /// <summary>
        /// 表示访问字段或属性
        /// </summary>
        /// <param name="exp"></param>
        /// <returns></returns>
        public string Resolve(Expression exp)
        {
            string expString = exp.ToString();
            if (expString.StartsWith("value(") || (expString.Contains(",") && expString.Contains(":")))
            {
                var result = Expression.Lambda(exp).Compile().DynamicInvoke();
                if (result == null)
                {
                    return "null";
                }
                else if (result is ValueType || result is string || result is DateTime)
                {
                    _expression.SetParameter(_expression.GetValueType(result));
                    return _expression.GetParamName();
                }
                else if (result.GetType().IsArray)
                {
                    //#2022.02.04
                    StringBuilder sb = new StringBuilder();
                    foreach (var item in (Array)result)
                    {
                        _expression.SetParameter(item);
                        sb.Append(_expression.GetParamName()).Append(",");
                    }
                    return sb.ToString(0, sb.Length - 1);
                }
                else if(result.GetType().FullName.Contains("List") || result.GetType().FullName.Contains("Enumerable"))
                {
                    //#2022.02.02
                    StringBuilder sb = new StringBuilder();
                    foreach (var item in result as IEnumerable)
                    {
                        _expression.SetParameter(item);
                        sb.Append(_expression.GetParamName()).Append(",");
                    }
                    return sb.ToString(0, sb.Length - 1);
                }
            }
            else
            {
                MemberExpression me = exp as MemberExpression;
                string declaringType = me.Member.DeclaringType.ToString();
                if (declaringType == "System.DateTime")
                {
                    switch (me.Member.Name)
                    {
                        case "Now":
                            return _expression.SqlDialect.GetDate;
                        case "Year":
                            return _expression.SqlDialect.Year(_expression.Resolve(me.Expression));
                        case "Month":
                            return _expression.SqlDialect.Month(_expression.Resolve(me.Expression));
                        case "Day":
                            return _expression.SqlDialect.Day(_expression.Resolve(me.Expression));
                        case "Hour":
                            return _expression.SqlDialect.Hour(_expression.Resolve(me.Expression));
                        default:
                            throw new Exception("unsupported expression");
                    }
                }
                if (declaringType == "System.String")
                {
                    string methodName = me.Member.Name;
                    switch (methodName)
                    {
                        case "Length":
                            return _expression.SqlDialect.Length(_expression.Resolve(me.Expression));
                        default:
                            throw new Exception("unsupported expression");
                    }
                }

                //当前属性所属类型
                Type entityType = me.Member.ReflectedType;
                if (_expression.IsPrefix)
                {
                    //i.t1.id = t1.id 、 i.t1 = t1.*
                    string expression = me.ToString();
                    string[] arguments = expression.Split('.');
                    if (_expression.IsSubquery && arguments.Length == 2)
                    {
                        //兼容子查询
                        arguments = new string[] { arguments[0], arguments[0], arguments[1] };
                    }
                    string prefix = arguments[1];
                    switch (arguments.Length)
                    {
                        case 2:
                            return prefix + ".*";
                        case 3:
                            string colName = _expression.GetColumnName(entityType, me.Member.Name);
                            return prefix + "." + (_expression.IsQuote ? _expression.SqlDialect.SetSqlName(colName) : colName);
                    }
                }
                else
                {
                    string colName = _expression.GetColumnName(entityType, me.Member.Name);
                    return _expression.IsQuote ? _expression.SqlDialect.SetSqlName(colName) : colName;
                }
            }
            return "";
        }
    }
}
